웹개발 및 최신 테크 소식을 전하는 블로그, 웹이즈프리

HOME > vuejs

[VueJS] v-slot을 사용하여 컴포넌트에 템플릿 추가하는 방법과 slot exist 확인하기

Last Modified : 2021-12-23 / Created : 2021-07-27
15,210
View Count

VueJS에서 하위 컴포넌트로 데이터를 전달하는 방법도 있지만 원하는 템플릿, 태그 등을 추가하는 것도 가능합니다. 이 경우 잘 알려진 방법으로 slot을 사용하는 방법이 있습니다. 아래는 VueJS에서 slot을 사용하는 방법에 대하여 알아보려고 합니다.



# VueJS에서 하위 컴포넌트에 태그 전달하기

공식 웹사이트를 찾아보니 기존의 slot을 사용하는 방법식 구현이 가능하기는 하지만 deprecated 되었으므로 v-slot을 사용하라고 하니 참고하시기 바랍니다. 여기서도 v-slot을 사용하는 방법을 알아보겠습니다. 그리고 slot의 존재 여부를 확인하여 방법도 같이 알아봅니다.

@ slot 또는 v-slot을 사용하는 무엇을 할 수 있을까요?
이미 아시는 경우 다음의 v-slot으로 넘어가셔도 됩니다. slot 또는 v-slot의 사용 목적은 만약 각각의 하위 컴포넌트 마다 다른 아이콘을 추가하고 싶을때가 좋은 예입니다. 즉 아래와 같이 각각 다른 아이콘을 적용하는 것이 가능하게 됩니다.
<ParentComponent>
  <template>
    <div>
      <ChildAComponent>
        <i class="icon icon-arrow" />
      </ChildAComponentA>

      <ChildBComponent>
        <i class="icon icon-close" />
      </ChildBComponent>
    </div>
  </template>
</ParentComponent>

여기서는 부모 컴포넌트가 각각의 ChildA와 ChildB 컴포넌트에 서로 다른 icon 클래스를 가진 태그를 전달하였습니다. 위 예제는 일반적인 slot 사용의 목적입니다. v-slot의 경우 slot 자체에 이름을 추가할 수 있는데 이처럼 이름을 사용할 경우 하나의 컴포넌트에서도 body, footer처럼 나누어서 전달하는 것이 가능하게 됩니다.


! v-slot을 사용하는 방법

이제 v-slot을 사용하는 방법부터 알아봅니다. 상위 컴포넌트에서는 하위로 전달할 경우 template 태그를 사용하되 v-slot 어트리뷰트에 slot이름을 사용하여 하위 컴포넌트에 전달해야 합니다.

<template v-slot:(이름)></template>


여기서 사용된 v-slot의 이름은 전달받은 자식 컴포넌트에서 해당 요소를 어디에 적용할 지 구분하는데 사용됩니다.아래는 간단한 예제로 이렇게 사용한다고 보시면 됩니다. 먼저 부모 요소에서 footer 이름의 v-slot을 만들어 전달할 경우입니다. 이때도 template을 사용합니다.
<div>
  ...
  <ChildComponent>
    <template v-slot:footer>
      <span>webisfree.com</span>
    </template>
  </ChildComponent>
</div>

이제 하위 컴포넌트 ChildComponent에서는 v-slot을 사용하여 전달 받게 됩니다. 이때 name 속성에 해당하는 slot 이름 footer를 사용합니다.
<div class="footer">
  ...
  <slot name="footer" />
</div>

위 예제처럼 v-slot을 사용하는 방법은 간단합니다. 추가로 만약 하나의 컴포넌트에 footer 외에 다른 v-slot도 전달하려면 어떻게 하는지 알아봅니다.


! 하위 컴포넌트에 v-slot 여러 개 사용하기

v-slot을 사용할 경우 여러 개의 template을 각기 다른 이름으로 사용할 수 있다고 알았는데요 이를 자식 요소에 전달하여 여러개의 slot을 전달(multiple slots)하는 것이 가능하죠. 예를들어 아래는 body, footer 두 개를 사용한 예제입니다.

<div>
  <template v-slot:body>
    <h3>Welcome to Webisfree.com</h3>
  </template>
  <template v-slot:footer>
    <h3>Webisfree.com</h3>
  </template>
</div>

두 개의 template을 사용하였습니다. 이제 아래와 같이 하위 컴포넌트에서 body, footer로 나누어 전달 받아야겠습니다.
<div class="content">
  <div class="body">
    <slot name="body" />
  </div>
  <div class="footer">
    <slot name="footer" />
  </div>
</div>

이처럼 사용 방법은 매우 간단합니다~ 하나 이상 또는 여러 개의 slot을 전달할 수 있게되었습니다.


! slot의 존재 여부를 확인하는 방법

하위 컴포넌트에서는 slot의 여부에 따라 특정 태그를 보이거나 숨길 필요도 있을 것 입니다. 예를들어 아래의 div 클래스 footer의 경우 footer 이름의 slot이 전달되지 않는다면? 이 경우 굳이 보여줄 필요가 없을 것 입니다. 이때 아래와 같이 적용할 수 있습니다. computed에 isExistFooter라는 값을 하나 선언하여 확인하는 방법입니다.
<template>
  <div
    v-if="isExistFooter"
    class="footer"
  >
    <slot name="footer" />
  </div>
</template>

<script>
export default {
  computed: {
    isExistFooter: function() {
      return this.$slots.footer ? true : false;
    }
  },
  ...
}
</script>

위 예제는 살펴보면 computed 내부의 함수 isExistFooter는 this.$slots를 사용하였습니다. 여기서 $slots는 해당 컴포넌트에 사용되는 모든 slots에 접근할 수 있으며 아래처럼 이름으로 접근하는 것도 가능합니다. 
return this.$slots.footer ? true : false;

이처럼 this.$slots.footer를 사용하여 footer 이름의 slot의 존재 여부에 따라 true, false의 불리언으로 반환하는 것이 가능하고 이를 사용하여 v-if처럼 분기문에 적용하는 것도 가능합니다.


여기가지 VueJS에서 v-slot을 사용하는 방법에 대하여 몇 가지 방법들을 알아보았습니다.
아래의 글도 찾고 계시지 않나요?

    Previous

    [VueJS] 드래그앤드랍 구현 라이브러리, vuedraggable

    Previous

    Vuex store에서 commit, dispatch 메소드를 전역으로 실행하는 방법